/*
 * Copyright (C) 2013～2023 上海颐凡软件科技有限公司
 * Yfann Software Technology (Shanghai) Co.,LTD
 * All Rights Reserved.
 * 公司网址: www.yfann.com
 * 365IT教育网，成就您优秀架构师之梦！
 * 平台网址: www.365itedu.com
 */
package com.yfann.web.base.sys.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.StrutsRequestWrapper;
import org.springframework.beans.BeanUtils;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
import com.yfann.sword.web.fwk.Service;
import com.yfann.sword.web.fwk.bean.AuthBean;
import com.yfann.sword.web.fwk.bean.UIOBean;
import com.yfann.sword.web.fwk.consts.FrameworkConst;
import com.yfann.sword.web.fwk.dao.QueryDAO;
import com.yfann.sword.web.fwk.dao.UpdateDAO;
import com.yfann.sword.web.fwk.exception.ApplicationException;
import com.yfann.sword.web.fwk.message.ApplicationErrorMessage;
import com.yfann.sword.web.fwk.message.ApplicationMessage;
import com.yfann.sword.web.fwk.util.DateUtil;
import com.yfann.sword.web.fwk.util.MD5Util;
import com.yfann.sword.web.fwk.util.PropertyUtil;
import com.yfann.sword.web.fwk.util.RequestUtil;
import com.yfann.sword.web.fwk.util.StringUtil;
import com.yfann.web.base.entity.dto.TSYS02InputDto;
import com.yfann.web.base.entity.dto.TSYS02OutputDto;
import com.yfann.web.base.entity.dto.TSYS04OutputDto;
import com.yfann.web.base.sys.consts.SYSConst;
import com.yfann.web.base.sys.dto.SYS0101S01S03InputDto;
import com.yfann.web.base.sys.dto.SYS0101S01S03OutputDto;
import com.yfann.web.base.sys.form.SYS0101S01Form;

/**
 * 登录页面业务处理类。
 * 
 * <pre>
 * 修改履历
 * -----------------------------------------------------------------------------
 *         VERSION       DATE            BY       CHANGE/COMMENT
 * -----------------------------------------------------------------------------
 *          1.0         2013/10/11      颜廷吉            create
 * -----------------------------------------------------------------------------
 * </pre>
 */
public class SYS0101S01LoginService implements Service {
    /**
     * 期待处理返回结果
     */
    private static final String EXPECT_EVENT = "loginSuccess";

    /**
     * 异常返回结果
     */
    private static final String EXCEPTION_EVENT = "forwardInput";

    /**
     * 密码有效期限过期返回结果
     */
    private static final String PWD_EXPIRE_EVENT = "forwardPwdExpire";

    /**
     * 数据访问DAO
     */
    private QueryDAO queryDAO;

    /**
     * 数据更新DAO
     */
    private UpdateDAO updateDAO;

    /**
     * 设定数据访问DAO。
     * @param queryDAO QueryDAO
     */
    public void setQueryDAO(QueryDAO queryDAO) {
        this.queryDAO = queryDAO;
    }

    /**
     * 设定数据更新DAO。
     * @param updateDAO UpdateDAO
     */
    public void setUpdateDAO(UpdateDAO updateDAO) {
        this.updateDAO = updateDAO;
    }

    /**
     * 业务逻辑执行。
     * @return String
     */
    @SuppressWarnings("unchecked")
    @Override
    public String executeService() {
        ActionContext actionContext = ActionContext.getContext();
        StrutsRequestWrapper request = (StrutsRequestWrapper) actionContext.getValueStack().getContext().get(StrutsStatics.HTTP_REQUEST);
        String i18LanguageName = RequestUtil.getUserI18LanguageName(request);
        Map<String, Object> sessionMap = actionContext.getSession();
        ValueStack valueStack = actionContext.getValueStack();

        SYS0101S01Form sys0101S01Form = (SYS0101S01Form) valueStack.findValue("sys0101S01Form");

        // 验证校验码
        String validateImageCode = (String) sessionMap.get("validateImageCode");
        if (validateImageCode != null && !validateImageCode.equalsIgnoreCase(sys0101S01Form.getValidateCd())) {
            List<ApplicationErrorMessage> appErrorMsgList = (List<ApplicationErrorMessage>) valueStack
                    .findValue(FrameworkConst.APP_ERROR_MESSAGE_LIST_KEY);
            appErrorMsgList.add(new ApplicationErrorMessage("E_SYS_0004", new String[] { "sys0101S01Form_validateCd" }));
            throw new ApplicationException(EXCEPTION_EVENT);
        }

        // 取得用户信息
        String userId = sys0101S01Form.getUserId();
        TSYS02InputDto tsys02DaoInput = new TSYS02InputDto();
        tsys02DaoInput.setUserId(userId);
        TSYS02OutputDto userInfo = queryDAO.executeForObject("TSYS.TSYS02_S01", tsys02DaoInput, TSYS02OutputDto.class);

        // 判断用户账号
        if (userInfo != null && MD5Util.getMD5(sys0101S01Form.getPwd()).equals(userInfo.getNowPwd())) {

            // 判断是否被停止
            if (SYSConst.USER_STATUS_STOP_002.equals(userInfo.getStatusCd())) {
                List<ApplicationErrorMessage> appErrorMsgList = (List<ApplicationErrorMessage>) valueStack
                        .findValue(FrameworkConst.APP_ERROR_MESSAGE_LIST_KEY);
                appErrorMsgList.add(new ApplicationErrorMessage("E_SYS_0001", new String[] { "sys0101S01Form_validateCd" }));
                throw new ApplicationException(EXCEPTION_EVENT);
            }

            // 判断登陆功能是否被阻塞
            String blockLoginAuth = queryDAO.executeForObject("SYS.SYS0101S01_S01", userId, String.class);
            if (StringUtil.isNotEmptStr(blockLoginAuth)) {
                // 阻塞异常
                return "blockLoginError";
            }

            // 初始化UIO
            UIOBean uioBean = new UIOBean();

            // 设定用户基本信息
            uioBean.setUserName(userInfo.getUserName());
            uioBean.setUserId(userInfo.getUserId());
            Integer currentLoginTimes = userInfo.getLoginTimes() + 1;
            uioBean.setLoginTimes(currentLoginTimes);
            uioBean.setLastLoginTime(userInfo.getLastLoginTime());

            // 设定用户权限信息
            List<AuthBean> authBeanList = queryDAO.executeForObjectList("SYS.SYS0101S01_S02", userId);
            uioBean.setAuthBeanList(authBeanList);

            // session里设定用户信息
            sessionMap.put(FrameworkConst.USER_INFO_OBJECT_KEY, uioBean);

            // session里设定用户一页显示条目个性信息
            sessionMap.put(FrameworkConst.PAGE_SIZE_KEY, userInfo.getPageSize());

            // session里设定用户翻页组大小个性信息
            sessionMap.put(FrameworkConst.EXTEND_PAGE_SIZE_CD_KEY, userInfo.getExtendPageSizeCd());

            // session里设定用户皮肤个性信息
            sessionMap.put(FrameworkConst.USER_SKIN_KEY, userInfo.getSkinCd());

            // session里设定动态编码信息
            HashMap<String, TreeMap<String, String>> dynCodeHashMap = getDynCodeHashMap(i18LanguageName);
            Iterator<String> it = dynCodeHashMap.keySet().iterator();
            it = dynCodeHashMap.keySet().iterator();
            while (it.hasNext()) {
                String key = (String) it.next();
                sessionMap.put(key, dynCodeHashMap.get(key));
            }

            // session里面设置Menu信息
            sessionMap.put("userMenu", getMenuContents(userId, request));
            
            // session里面设置最新消息总查询件数
           // MSG0101S01InputDto msg0101S01InputDto = new MSG0101S01InputDto();
            // 消息状态
//            msg0101S01InputDto.setStatusCd("001");
//            msg0101S01InputDto.setAcceptUserId(uioBean.getUserId());
//            Integer newMsgNum = queryDAO.executeForObject("MSG.MSG0101S01_S02", msg0101S01InputDto, Integer.class);
//            sessionMap.put("NEW_MSG_NUM", newMsgNum);
//            
//            // 查询审核状态
//            TOFC01InputDto tofc01InputDto = new TOFC01InputDto();
//            tofc01InputDto.setApplyUserId(uioBean.getUserId());
//            TOFC01OutputDto tofc01DaoOutput = queryDAO.executeForObject("TOFC.TOFC01_S01", tofc01InputDto, TOFC01OutputDto.class);
//            if(tofc01DaoOutput!=null){
//                sessionMap.put("CHECK_STATUS_CD", tofc01DaoOutput.getStatusCd());
//            }
            
            // 更新登录信息
            BeanUtils.copyProperties(userInfo, tsys02DaoInput);
            tsys02DaoInput.setLoginTimes(currentLoginTimes);
            tsys02DaoInput.setLastLoginTime(DateUtil.getFormatedCurrentDate(FrameworkConst.YYYYMMDDHHMMSS));
            tsys02DaoInput.setUserId(userId);
            tsys02DaoInput.setUpdateTime(DateUtil.getFormatedCurrentDate(FrameworkConst.YYYYMMDDHHMMSS));
            tsys02DaoInput.setUpdateUserId(userId);
            tsys02DaoInput.setVersionNo(userInfo.getVersionNo());
            updateDAO.execute("TSYS.TSYS02_U01", tsys02DaoInput);

            // 判断密码有效期限过期
            String currentDay = DateUtil.getFormatedCurrentDate(FrameworkConst.YYYYMMDD);

            String pwdValidPeriod = PropertyUtil.getProperty("pwdValidPeriod");
            String pwdInValidDay = DateUtil.getFormatedCalculateDay(userInfo.getPwdUpdateDay(), Integer.valueOf(pwdValidPeriod),
                    FrameworkConst.YYYYMMDD);
            if (Integer.parseInt(currentDay) >= Integer.parseInt(pwdInValidDay)) {
                List<ApplicationErrorMessage> appErrorMsgList = (List<ApplicationErrorMessage>) valueStack
                        .findValue(FrameworkConst.APP_ERROR_MESSAGE_LIST_KEY);
                appErrorMsgList.add(new ApplicationErrorMessage("E_SYS_0002"));
                throw new ApplicationException(PWD_EXPIRE_EVENT);
            }

            // 提示密码修改
            String pwdRemindPeriod = PropertyUtil.getProperty("pwdRemindPeriod");
            String pwdRemindStartDay = DateUtil.getFormatedCalculateDay(pwdInValidDay, -Integer.valueOf(pwdRemindPeriod), FrameworkConst.YYYYMMDD);
            if (Integer.parseInt(currentDay) >= Integer.parseInt(pwdRemindStartDay)) {
                List<ApplicationMessage> appMsgList = (List<ApplicationMessage>) valueStack.findValue(FrameworkConst.APP_MESSAGE_LIST_KEY);
                appMsgList.add(new ApplicationMessage("I_SYS_999"));
                // TODO 最好给一个系统消息
            }

        } else {
            List<ApplicationErrorMessage> appErrorMsgList = (List<ApplicationErrorMessage>) valueStack
                    .findValue(FrameworkConst.APP_ERROR_MESSAGE_LIST_KEY);
            appErrorMsgList.add(new ApplicationErrorMessage("E_SYS_0003", new String[] { "sys0101S01Form_userId", "sys0101S01Form_pwd" }));
            throw new ApplicationException(EXCEPTION_EVENT);
        }
        return EXPECT_EVENT;
    }

    /**
     * 取得菜单处理。
     * @return 菜单 String
     */
    private String getMenuContents(String userId, StrutsRequestWrapper request) {
        String i18LanguageName = RequestUtil.getUserI18LanguageName(request);
        SYS0101S01S03InputDto sys01SC01S03DaoInput = new SYS0101S01S03InputDto();
        sys01SC01S03DaoInput.setMenuLg(i18LanguageName);
        sys01SC01S03DaoInput.setUserId(userId);
        List<SYS0101S01S03OutputDto> fatherMenuList = queryDAO.executeForObjectList("SYS.SYS0101S01_S03", sys01SC01S03DaoInput);
        List<SYS0101S01S03OutputDto> chiderMenuList = queryDAO.executeForObjectList("SYS.SYS0101S01_S04", sys01SC01S03DaoInput);
        List<SYS0101S01S03OutputDto> allOrderedmenuList = new ArrayList<SYS0101S01S03OutputDto>();
        for (SYS0101S01S03OutputDto fatherMenu : fatherMenuList) {
            allOrderedmenuList.add(fatherMenu);
            for (SYS0101S01S03OutputDto chiderMenu : chiderMenuList) {
                if (fatherMenu.getMenuId().equals(chiderMenu.getFatherId())) {
                    allOrderedmenuList.add(chiderMenu);
                }
            }
        }

        StringBuilder strBuilder1 = new StringBuilder();
        StringBuilder strBuilder2 = new StringBuilder();
        Integer menuNo = 1;
        Boolean firstMenu = true;

        strBuilder1.append("<div id=\"left_menu\">");
        strBuilder1.append("    <ul id=\"menu\"> \r\n");
        for (SYS0101S01S03OutputDto menu : allOrderedmenuList) {
            if (firstMenu && !StringUtil.isNotEmptStr(menu.getFatherId())) {
                firstMenu = false;
                strBuilder1.append("        <li class=\"item menu_character\"><a href=\"javascript:void(0)\" class=\"title\" name=\"" + menuNo
                        + "\">" + menu.getMenuName() + "</a> \r\n");
            } else {
                if (!StringUtil.isNotEmptStr(menu.getFatherId())) {
                    strBuilder1.append("            <ul id=\"opt_" + menuNo + "\" class=\"optiton\"> \r\n");
                    strBuilder1.append(strBuilder2);
                    strBuilder1.append("            </ul> \r\n");
                    strBuilder1.append("        </li> \r\n");
                    strBuilder2.delete(0, strBuilder2.length());

                    menuNo++;
                    strBuilder1.append("        <li class=\"item menu_character\"><a href=\"javascript:void(0)\" class=\"title\" name=\"" + menuNo
                            + "\">" + menu.getMenuName() + "</a> \r\n");
                } else {
                    strBuilder2.append("                <li><a href=\"" + request.getContextPath() + menu.getAuthURL() + "\">" + menu.getMenuName()
                            + "</a></li> \r\n");
                }
            }
        }
        strBuilder1.append("            <ul id=\"opt_" + menuNo + "\" class=\"optiton\"> \r\n");
        strBuilder1.append(strBuilder2);
        strBuilder1.append("            </ul>\r\n");
        strBuilder1.append("        </li>\r\n");

        strBuilder1.append("</ul> \r\n");
        strBuilder1.append("</div> \r\n");

        return strBuilder1.toString();
    }

    private HashMap<String, TreeMap<String, String>> getDynCodeHashMap(String i18LanguageName) {
        HashMap<String, TreeMap<String, String>> dynCodeHashMap = new HashMap<String, TreeMap<String, String>>();
        int dynamicCodeNum = 1;

        while (StringUtil.isNotEmptStr(PropertyUtil.getProperty("dynamic.code.key." + dynamicCodeNum))) {
            String dynamicCodeKey = PropertyUtil.getProperty("dynamic.code.key." + dynamicCodeNum);
            String dynamicCodeSqlKey =PropertyUtil.getProperty("dynamic.code.sql.key." + dynamicCodeNum); 
            //String dynamicCodeSqlParameterKey = PropertyUtil.getProperty("dynamic.code.sql.parameter." + dynamicCodeNum);
            List<TSYS04OutputDto> codeValeList = queryDAO.executeForObjectList(dynamicCodeSqlKey,null);
            TreeMap<String, String> treeMap = new TreeMap<String, String>();
            treeMap.put(FrameworkConst.CODE_FIRST_KEY, PropertyUtil.getProperty( i18LanguageName + "." + "codeFirstValue"));
            for(int i = 0;i<codeValeList.size();i++){
                TSYS04OutputDto tsys04OutputDto = codeValeList.get(i);
            treeMap.put(tsys04OutputDto.getRoleId(), tsys04OutputDto.getRoleName());
            }
            dynCodeHashMap.put(dynamicCodeKey, treeMap);
            dynamicCodeNum++;
        }

        return dynCodeHashMap;
    }
}
